#!/usr/bin/perl

# This script aims to provide a better rt tool with following features:
# 1. Run rt with a user-defined baseline.
#    Run a 'RT' with my code without fix as baseline,
#    so we will not be bothered by the diffs caused by other guys
# 2. Provide better analysis of diffs, 
# 3. Provide backward compatibility with old rt tools
# 4. Provide faster RT by using parallel method and user-defined plan mode restrictions

use strict;
#use warnings;

# Columns below start from 0.
use constant COL_EDD => 116;
use constant COL_ECC => 117;
use constant COL_CS_MODE => 181;
use constant DATA_121 => '/mrpdev/msc/psldevrt/';
use constant DATA_122 => '/mrpdev/msc/psmdevrt/';

# No longer used
use constant LIST_121_QA => '/home/yantang/rt_natty/121_QA.list';
use constant LIST_121_UT => '/home/yantang/rt_natty/121_UT.list';
use constant LIST_122_QA => '/home/yantang/rt_natty/122_QA.list';
use constant LIST_122_UT => '/home/yantang/rt_natty/122_UT.list';

my %modeExclude;
my %modeInclude;

my $isEdd;
my $fromRTTxt;

my $exeA;
my $exeB;

my $mailAddr; # When RT ended, report result to this mail address if defined

my $rtDataDir;

my @QAList;
my @UTList;

# load: loadColumnNamesMap
# find: getColumnNameFromIndex
my %columnNamesMap; # MSLDXXX.dat => [ col1,col2,col3 ]

# A list of plans that will be run in the final.
my @planToRunList; # [data location (UT/QA), planName, csMode, ecc|edd ]

my $startTime = time;

#main
&processArgs();
&getRTDataDir();
&filterRTPlans($fromRTTxt,\%modeInclude,\%modeExclude,$isEdd);

my $allPlanNum = $#QAList + $#UTList + 2;
my $planToRunNum = $#planToRunList + 1;
print "There are $allPlanNum in all. Plans to run in total: $planToRunNum\n";


my $maxProcess = 4;
my $child;
for( $child = 0; $child<$maxProcess; $child++ )
{
	print "Forking child $child...\n";
	my $pid = fork;
	if( $pid == 0 )
	{
		open LOG, ">rt_natty.$child" or die "Unable to open rt_natty.$child as log output:$!\n";
		
		my $failCnt = 0;
		my $diffCnt = 0;
		for( my $i=$child; $i<=$#planToRunList; $i+=$maxProcess )
		{
			my $plan = $planToRunList[$i];
			my $location = $plan->[0];
			my $planName = $plan->[1];
			my $log = &runWorkUnit( $location, $planName, $exeA, $exeB );
			print LOG $log."\n";
			print "#$child $log\n";
			
			$failCnt++ if( $log =~ /FAIL/ );
			$diffCnt++ if( $log =~ /DIFF/ );
		}
		
		# Write such line as end of current log
		print LOG "LOG_END#DIFF=$diffCnt,FAIL=$failCnt\n";
		close LOG;
		exit 0; #Quit fork process in child process
	}
}

while( wait != -1 ){};

print "All processes finished successfully\n";

#Merge Log
my $totalFail = 0;
my $totalDiff = 0;
open LOG, ">rt_natty.txt" or die "Unable to open rt_natty.txt as log output:$!\n";

my $declaration = <<END;
This file is the RT result generated by rtNatty.pl ( /home/yantang/tools/rtNatty.pl )

Arguments taken: @ARGV
Total: $allPlanNum  To Run: $planToRunNum\n\n
END

print LOG $declaration;
for( $child = 0; $child<$maxProcess; $child++ )
{
	open CHILD_LOG, "rt_natty.$child" or die "Unable to open rt_natty.$child for reading:$!\n";
	
	while( <CHILD_LOG> )
	{
		if( /LOG_END#DIFF=(\d+),FAIL=(\d+)/ )
		{
			$totalDiff += $1;
			$totalFail += $2;
			last; #This is the last line.
		}
		else{
			print LOG $_;
		}
	}
	close CHILD_LOG;
	
	system "rm -rf rt_natty.$child"; #Delete child log
}

my $endTime = time;
my $timeInterval = ($endTime - $startTime);

print LOG "\n\nFail: $totalFail  Diff:$totalDiff\n";
print LOG "Time taken = $timeInterval seconds\n";
print "Fail: $totalFail  Diff:$totalDiff\n";
close LOG;

print "Log has been saved as rt_natty.txt\n";



if( defined $mailAddr )
{
	&reportResult( $mailAddr );
}

print "Job Complete! Time taken= $timeInterval\n";


sub printUsage
{
	my $usage = <<END;
rtNatty.pl msonew1 [msonew2] [mode!=(1-3)] [mode=(1-3)] [ecc|edd]  [rt_result.txt]
Run a default RT: selfrt.pl msonew
Compare rt results of two exe: selfrt.pl msonew1 msonew2

rtNatty.pl update 
Reserved option, I use this to update detail list of plans
END
	print $usage;
	exit 0;
}

# Process args
sub processArgs
{
	if( $#ARGV == -1 ) {
		&printUsage;
	}
	
	foreach my $arg( @ARGV )
	{
		if( $arg =~ /.txt/ ) {
			$fromRTTxt = $arg;
		}
		elsif( $arg eq 'update' ) {
			&updatePlanList();
			exit 0;
		}
		elsif( $arg =~ /mode=(\d)/ ) {
			$modeInclude{$1}=1;
		}
		elsif( $arg =~ /mode!=(\d)/ ) {
			$modeExclude{$1}=1;
		}
		elsif( $arg =~ /(ecc|edd)/ ) {
			$isEdd = ($1 eq 'edd')?1:0;
		}
		elsif( $arg =~ /@/ ) {
			$mailAddr = $arg;
		}
		else{
			die "Executable doesn't exist or wrong argument:$arg\n" unless -e $arg;
			die "Unknow argument:$arg\n" unless not defined $exeB;
			if( defined $exeA )
			{
				$exeB = $arg;
			}else{
				$exeA = $arg;
			}
		}
	}

	# Debug
	print "Use exe: $exeA $exeB\n" unless not defined $exeB;
	print "Default RT using $exeA\n" unless defined $exeB;
	print "Probe plan diffs in file: $fromRTTxt\n" if defined $fromRTTxt;
	print "Include these modes:";
	foreach my $incMode(keys %modeInclude)
	{
		print "$incMode\t";
	}
	print "\n";
	print "Except these modes:";
	foreach my $expMode(keys %modeExclude)
	{
		print "$expMode\t";
	}
	print "\n";
	print "IsEDD: $isEdd\n" if defined $isEdd;
}

# Get the branch env, and decide which rt data directory to use
# Die when it's not available
# return: RT data path
sub getRTDataDir
{
	my $mso_top = $ENV{'MSO_TOP'};
	if( defined $mso_top and $mso_top =~ /(121|122)/ )
	{
		my $branch = $1;
		if( $branch eq '121' ) {
			$rtDataDir = DATA_121;
			@QAList = readListFromFile( LIST_121_QA );
			@UTList = readListFromFile( LIST_121_UT );
			&loadColumnNamesMap( '/home/yantang/rt_natty/121.ColumnNames' );
		}
		if( $branch eq '122' ) {
			$rtDataDir = DATA_122;
			@QAList = readListFromFile( LIST_122_QA );
			@UTList = readListFromFile( LIST_122_UT );
			&loadColumnNamesMap( '/home/yantang/rt_natty/122.ColumnNames' );
		}
	}else{
		die "Unrecognized branch or env MSO_TOP not set";
	}
}

# Load all column name files into map columnNamesMap
# p0: ColumnNames dir to read from
sub loadColumnNamesMap
{
	my $columnDir = $_[0];
	
	print "Loading column names from $columnDir\n";
	foreach my $file ( glob $columnDir.'/*.dat' )
	{
		$file =~ /\/(MSLD.*\.dat)/;
		my $shortName = $1;
		my @columns;
		open COL, $file or die "Unable to open $file for reading:$!\n";
		while( <COL> )
		{
			chomp;
			if( /([0-9]+)\s+(.*)$/ )
			{
				@columns[ $1-1 ] = $2;
				#print "$1\t$2\n";
			}
		}
		close COL;
		
		$columnNamesMap{ $shortName } = \@columns;
		
		#print "#Loaded $#columns from $shortName\n";
	}
}

# Get the column name from index given ( 0-N )
# p0: flat file name
# p1: index
# return: column name string
sub getColumnNameFromIndex
{
	my $file = $_[0];
	my $index = $_[1];
	
	my $ret = "unknown";
	
	if( $file =~ /\// ) {
		$file =~ /\/(MSLD.*\.dat)/ ;
		$file = $1;
	}
	
	if( exists $columnNamesMap{ $file } )
	{
		my $columns = $columnNamesMap{ $file };
		if( defined $columns->[ $index ] )
		{
			$ret = $columns->[ $index ];
		}
	}
	
	$ret;
}

# Filter the plans so we can decide which plan to use
# p0: rt_text
# p1: hash ref of plan modes that includes
# p2: hash ref of plan modes that excludes
# p3: ecc|edd plan
# return: a list of plans that to be running
sub filterRTPlans
{
	my $fromRTTxt = $_[0];
	my $incRef = $_[1];
	my $excRef = $_[2];
	my %modeInclude = %$incRef;
	my %modeExclude = %$excRef;
	my $planType = $_[3];
	
	# filter plans by a rt_result.txt, this will shields all other options
	if( defined $fromRTTxt ) { 
		open RT_DIFF, '<'.$fromRTTxt or die "Unable to open $fromRTTxt to read:$!\n";
		while( <RT_DIFF> )
		{
			chomp;
			if( /(.*)\s=\sDIFF/ ) {
				if( -d $rtDataDir.'UT/'.$1 ) {
					push @planToRunList, [$rtDataDir."UT/$1",$1];
				}elsif( -d $rtDataDir.'QA/'.$1 ) {
					push @planToRunList, [$rtDataDir."QA/$1",$1];
				}
			}
		}
	} else {
		# Filter plans by only allowing mode that matches
		
		my @kInclude = keys %modeInclude;
		my @kExclude = keys %modeExclude;
		
		my $i;
		for( $i=0; $i<=$#QAList; $i++ )
		{
			my $plan = $QAList[$i];
			if( $#kInclude != -1 and not exists $modeInclude{$plan->[1]} )
			{
				undef $QAList[$i];
			}
			if( $#kExclude != -1 and exists $modeExclude{$plan->[1]} )
			{
				undef $QAList[$i];
			}
			if( defined $isEdd and $plan->[2] != 1 )
			{
				undef $QAList[$i];
			}
			
			if( defined $QAList[$i] )
			{
				push @planToRunList, [ $rtDataDir."QA/$plan->[0]",$plan->[0] ];
			}
		}
		
		for( $i=0; $i<=$#UTList; $i++ )
		{
			my $plan = $UTList[$i];
			if( $#kInclude != -1 and not exists $modeInclude{$plan->[1]} )
			{
				undef $UTList[$i];
			}
			if( $#kExclude != -1 and exists $modeExclude{$plan->[1]} )
			{
				undef $UTList[$i];
			}
			if( defined $isEdd and $plan->[2] != 1 )
			{
				undef $UTList[$i];
			}
			
			if( defined $UTList[$i] ) 
			{
				push @planToRunList, [ $rtDataDir."UT/$plan->[0]",$plan->[0] ];
			}
		}		
	}
}

# helps to refresh plan list file so we can save much time in searching plan type/cs mode
# create plan list of all plans of 121/122 RT , and save them in 
# ~yantang/rt_natty/, named 121_QA.list 121_UT.list, 122_QA.list,122_UT.list respectively
sub updatePlanList
{
	print "Updating file list of 121/122 RT plans...\n";
	
	my @planList;
	
	#@planList = probeDirForPlanList( DATA_121.'QA' );
	@planList = readListFromRTSuite( DATA_121.'QA/list' );
	writeListToFile( \@planList, LIST_121_QA );
	#@planList = probeDirForPlanList( DATA_121.'UT' );
	@planList = readListFromRTSuite( DATA_121.'UT/list' );
	writeListToFile( \@planList, LIST_121_UT );
	#@planList = probeDirForPlanList( DATA_122.'QA' );
	@planList = readListFromRTSuite( DATA_122.'QA/list' );
	writeListToFile( \@planList, LIST_122_QA );
	#@planList = probeDirForPlanList( DATA_122.'UT' );
	@planList = readListFromRTSuite( DATA_122.'UT/list' );
	writeListToFile( \@planList, LIST_122_UT );
	
	print "Jobs done!\n";
}

# Read plan list from suite file, and probe the plan content
sub readListFromRTSuite
{
	my $suiteList = $_[0];
	
	my @planList;
	open SUITE_LIST, $suiteList or die "Unable to open $suiteList for reading:$!\n";
	
	$suiteList =~ /(.*)list$/;
	my $dataPath = $1;
	
	my %colMap = ( 'constrained_mode' => 1,
	'enforce_dem_due_dates' => 1,
	'enforce_cap_constraints' => 1,
	'daily_material_constraints' => 1,
    'weekly_material_constraints' => 1,
	'period_material_constraints' => 1,
	'daily_resource_constraints' => 1,
    'weekly_resource_constraints' => 1,
    'period_resource_constraints' => 1 );
	
	my $neededColumns = 'constrained_mode,enforce_dem_due_dates,enforce_cap_constraints,daily_material_constraints,weekly_material_constraints,period_material_constraints,daily_resource_constraints,weekly_resource_constraints,period_resource_constraints';

	while( <SUITE_LIST> )
	{
		chomp;
		next if( /#/ );
		next if( /^[^\d\w]+$/ ); #Skip that do not likely to be a plan record
		
		my $entry = $_;
		my $flatPlan = $dataPath.$entry.'/mbpoutput/MSLD_FLAT_PLAN.dat';
		if( $colMap{'constrained_mode'} == 1 ) {
			%colMap = &getColumnIndexHash( $flatPlan );
		}
		if( -e $flatPlan )
		{
	
			open FLAT_PLAN, $flatPlan or die "Unable to open $entry for reading:$!\n";
			my @lines = <FLAT_PLAN>;
			chomp $lines[0];
			my @values = split( //,$lines[0]);
			
			if( $#values > COL_CS_MODE )
			{	
				my $isEdd = ($values[$colMap{'enforce_dem_due_dates'}]==1)?1:0;
				my $csMode = $values[$colMap{'constrained_mode'}];
				
				###########################################################################
				# Thanks to damn mbp, I have to add more than 100 lines for their damn code
				# when constrained_mode = -23453, we have to deal with its 'real' mode.
				# Logic taken from mslflt.ppc in patch 17484362_R12.MSC.B
				###########################################################################
				
				if( $csMode == -23453 ) {
					if( $values[ $colMap{'daily_material_constraints'} ] == 2 and
						$values[ $colMap{'weekly_material_constraints'} ] == 2 and
						$values[ $colMap{'period_material_constraints'} ] == 2 and
						$values[ $colMap{'daily_resource_constraints'} ] == 2 and
						$values[ $colMap{'weekly_resource_constraints'} ] == 2 and
						$values[ $colMap{'period_resource_constraints'} ] == 2 
					){
						$csMode = 0;
					}else{
						$csMode = 1;
					}
					print "Adding $entry with cs mode -23453 as $csMode\n";
				}
				
				#print "#Adding $entry\n";
				push @planList, "$entry,$csMode,$isEdd";
			}else{
				print "No enough columns in $flatPlan: $#values columns given ( start from 0 )\n";
			}
			
			close FLAT_PLAN;
		}else{
			print "$entry doest exist, skip\n";
		}
	}
	close SUITE_LIST;
	
	@planList;
}

# To find all plans under given directory and load them into a list
# p0: data to probe
# return: plan list : [planName, constrained Mode, isEdd]
sub probeDirForPlanList
{
	my $dirName = $_[0];
	
	my @planList; #[planName, constrained Mode, isEdd]
	
	opendir DIR, $dirName or die "Unable to open directory $dirName:$!\n";
	
	my @files = readdir DIR;
	
	foreach my $entry (@files)
	{
		next if( $entry =~ /\./ ); #Skip dir contains dot
		next unless ( -d $dirName.'/'.$entry ); #Skip non-dir entries
		
		my $flatPlan = $dirName.'/'.$entry.'/mbpoutput/MSLD_FLAT_PLAN.dat';
		if( -e $flatPlan )
		{
			open FLAT_PLAN, $flatPlan or die "Unable to open $entry for reading:$!\n";
			my @lines = <FLAT_PLAN>;
			chomp $lines[0];
			my @values = split( //,$lines[0]);
			
			if( $#values > COL_CS_MODE )
			{
				my $ecc = $values[COL_ECC];
				
				my $isEdd = ($values[COL_EDD]==1)?1:0;
				my $csMode = $values[COL_CS_MODE];
				
				#print "#Adding $entry\n";
				push @planList, "$entry,$csMode,$isEdd";
			}else{
				print "No enough columns in $flatPlan: $#values columns given ( start from 0 )\n";
			}
			
			close FLAT_PLAN;
		}else{
			print "$entry doest exist, skip\n";
		}
	}
	
	closedir DIR;
	
	@planList;
}

# write a plan list to given file, clear original content if exists
# format: planName,csmode,isEdd
# p0: array ref of plan listm
# p1: file to write
sub writeListToFile
{
	my $refPlanList = $_[0];
	my $fileName = $_[1];
	
	open LIST_FILE, '>'.$fileName or die "Unable to open $fileName for writing: $!\n";
	
	foreach my $planRecord ( @$refPlanList )
	{
		print LIST_FILE "$planRecord\n";
	}
	
	close LIST_FILE;
}

# read plan list to be used from given file
# p0: file to use
# return: list from file
sub readListFromFile
{
	my $fileName = $_[0];
	
	print "#Reading list from $fileName\n";
	
	my @planList;
	open LIST_FILE, $fileName or die "Unable to open $fileName for reading:$!\n";
	while( <LIST_FILE> )
	{
		chomp;
		if( /(.*),(.*),(.*)/ ) {
			push @planList, [$1,$2,$3];
			#print "#read:$_\n";
		}
	}
	close LIST_FILE;
	
	@planList;
}

#Index returned begins from 0, so we can use to array easily
# It gets columnname hash from column files in /home/yantang/rt_natty/ by default
# If not found, take columns from MSC_TOP
sub getColumnIndexHash
{
	my %colIndex;
	my $fileName = $_[0];
	my $branch = '121';
	
	if( $fileName =~ /psl/ ) {
		$branch = '121'
	}elsif( $fileName =~ /psm/ ) {
		$branch = '122';
	}elsif( defined $_[1] ) {
		$branch = $_[1];
	}
	
	$fileName =~ /([^\/]+)$/;
	my $shortName =$1;
	my $columnFile = '/home/yantang/rt_natty/'.$branch.'.ColumnNames/$shortName';
	if( not -e $columnFile )
	{
		my $msc_top = $ENV{'MSC_TOP'};
		die "No env var MSC_TOP found while columns not available" unless ( defined $msc_top );
		$columnFile = $msc_top."/ColumnNames/$shortName";
		#Output load schema info so usr will know 
		die "Cannot find schema for $shortName" if( not -e $columnFile );
	}
	
	#Comment this to make output cleaner
	#print "Load schema from $columnFile\n";
	
	open COL_FILE , $columnFile or die "##getColumnIndexHash:Unable to open $columnFile :$!\n";
	
	my $index = 0;
	while( <COL_FILE> )
	{
		chomp;
		if( /([0-9]+)\s+(.*)$/ )
		{
			$colIndex{$2} = $1;
			#print "$1\t$2\n";
		}
	}
	
	close COL_FILE;
	return %colIndex;
}

# Get a index-columnName table, start from 0
sub getIndexColumnTable
{
	
}

# a awk utility directly inserted into perl so we don't need to create PIPES to call tak
#param0: condition in text format
#param1: columns to get, split by comma
#param2: flat file to be explored

#return: an reference to a double-direction array containing columns expected.
#Errors: when no records found or 
sub pawk
{
	my $condition = $_[0];
	my $action = $_[1];
	my $fileName = $_[2];
	my @dblArray;
	
	my %colIndex = &getColumnIndexHash($fileName);

	# /g returns results of an array matching reg
	foreach my $key( $condition =~ /([a-zA-Z_]+)[+-~=><& ]/g )
	{
		if( exists $colIndex{$key} )
		{
			my $index =  $colIndex{$key};
			$condition =~ s/$key/\$$index/;
		}
	}
	
	my $colCount = 0;
	$colCount++ while( $action =~ /,/g );
	
	foreach my $key( $action =~ /([a-zA-Z_]+)/g )
	{
		if( exists $colIndex{$key} )
		{
			my $index = $colIndex{$key};
			$action =~ s/$key/\$$index/;
		}
	}

	my $command = 'awk -F '. '\'{ if('. $condition . ') print '. $action .'}\'  ' . $fileName;
	#print "Command:$command\n";
	unless ( open PIPE, "-|" )
	{
		exec $command;
		exit;
	}
	
	my $recordCount = 0;
	while( <PIPE> )
	{
		my @values = split( /\s/, $_ );
		#If we encountered error, tell us what awk command we used, and the output as well
		die "##pawk: awk execution error\n##Command:$command\n##Output:$_\n" unless ($#values eq $colCount);
		push @dblArray, [@values];
		++$recordCount;
	}
	
	print STDERR "No output from awk on file $fileName \n" unless ( $recordCount ne 0 );
	close PIPE;
	
	\@dblArray;
}

# This functions complete a 'work unit' that will be done in one of the processes
# When running classic RT ( Only one exe specified in argument and compares output with RT mbpoutput_reference ),
# we take such a single exe running/diff as a 'work unit'.
# When running our self-defined RT , with two exe given and user want to compare their RT results, 
# we take the running process of two exe and their diff as a 'work unit'
# p0: location of the plan data dir 
# p1: planName
# p2: exeA
# p3: exeB
# return: a multi-line string that can be used in the log directly.
sub runWorkUnit
{
	my $dataLocation = $_[0];
	my $planName = $_[1];
	my $exeA = $_[2];
	my $exeB;
	$exeB = $_[3] if( defined $_[3] );

	my $log = "$planName ";
	
	if( -d $planName ) {
		system "rm -rf $planName >/dev/null";
	}
	
	mkdir $planName;
	chdir $planName;
	### Operate on under $planName ###
	mkdir 'data';
	#`ln -s $dataLocation/mbpinput data/mbpinput`;
	system "cp -r $dataLocation/mbpinput data/";
	mkdir 'data/mbpoutput';
	system "cp $dataLocation/mbpoutput/*.dat data/mbpoutput";
	
	system "../$exeA flatfile 0 Y 0 >logA"; 
	
	my $retA = system "grep \"Flat file Success\" logA >/dev/null";
	$retA = $retA >> 8;
	if( $retA != 0 ) {
		$log .= " FAIL:$exeA ";
	}
	
	my $refDir = 'data/mbpoutput_reference';
	my $retB = 0;
	if( defined $exeB ) {
		$refDir = 'data/mbpoutput_reference';
		system "cp -r data/mbpoutput $refDir >/dev/null";
		system "../$exeB flatfile 0 Y 0 >logB";
		$retB = system "grep \"Flat file Success\" logB >/dev/null";
		$retB = $retB >> 8;
		if( $retB != 0 ) {
			$log .= " FAIL:$exeB ";
		}
	}
	else{
		if( -e $dataLocation.'/mbpoutput_reference.zip' ) {
			my $unzipCommand = "unzip -o -q $dataLocation/mbpoutput_reference.zip -d data/ >/dev/null";
			#print "Command=$unzipCommand\n";
			system $unzipCommand;
			die "Unable to unzip mbpoutput_reference.zip for $planName\n" unless ( -e 'data/mbpoutput_reference' );
		}
		else{
			print "Error: Unable to find mbpoutput_reference.zip for $planName, SKIP\n";
			return;
		}
	}
	
	my $hasDiff = 0;
	# Run diff on plans that donot fail
	if( $retA == 0 and $retB == 0 )
	{
		my $retLog = &diffOutput( $refDir ,'data/mbpoutput' );
		if( $retLog ne "" )
		{
			$log .= $retLog;
			$hasDiff = 1;
		}
	}
	else{
		$hasDiff = 1;
	}
	
	chdir '..';
	
	# Clear up remains if there's no diff
	if( not $hasDiff ) {
		system "rm -rf $planName";
	}
	### Leave dir $planName
	
	$log;
}

# Compare .dat files under two mbpoutput dir
# p0: output1
# p1: output2
# return: a string contains the diff content. empty otherwise
sub diffOutput
{
	my $outA = $_[0];
	my $outB = $_[1];
	
	my $log = "";
	
	foreach my $file (glob $outA.'/*.dat')
	{
		next unless $file =~ /(MSLD.*\.dat)/;
		
		if( -e "$outB/$1" )
		{
			$log .= &compareFile( $file, "$outB/$1" );
		}else{
			$log .= "DIFF $file: Doesn't exist in $outB/$1\n";
		}
	}
	
	#print $log;
	$log;
}

# Compare two files. If it's not the same, we will analyze the columns with diff
# But we only analyze first diff line to save time!
# p0: 1st file
# p1: 2st file
# return: a string contains the diff analyzation. empty otherwise
sub compareFile
{
	my $diffRet = "";
	$_[0] =~ /(MSLD.*)\.dat$/;
	my $shortName = $1;
	
	open FA, $_[0] or die "Unable to open $_[0] for reading!\n";
	open FB, $_[1] or die "Unable to open $_[1] for reading!\n";
	
	my @linesA = <FA>;
	my @linesB = <FB>;
	
	if( $#linesA != $#linesB ) {
		$diffRet .= "DIFF $shortName: lines donot match: $#linesA $#linesB\n";
	}
	for( my $i=0;$i<=$#linesA and $i<=$#linesB ;$i++ )
	{
		if( $linesA[$i] ne $linesB[$i] )
		{
			$diffRet .= "DIFF $shortName at line $i:";
			my @va = split( //, $linesA[$i] );
			my @vb = split( //, $linesB[$i] );
			$diffRet .= "columns donot match $#va $#vb " if( $#va != $#vb );
			for( my $i=0;$i<=$#va and $i<=$#vb; $i++ )
			{
				if( $va[$i] ne $vb[$i] )
				{
					my $diffColName = &getColumnNameFromIndex( $_[0], $i );
					$diffRet .= $diffColName."($i) ";
				}
			}
			last;
		}
	}
	
	close FA;
	close FB;
	
	#print $diffRet;
	$diffRet;
}

# Report rt result to specified mail address
# p0: mail address
sub reportResult
{
    my $mailAddr = $_[0];
    my $subject  = '#RT Natty Report#';
    
    print "Sending report to $mailAddr\n";
    my $command = 'mail -s "'.$subject.'" '.$mailAddr.'<rt_natty.txt';
    system( $command );
}
